#pragma once

#include <iostream>
#include <queue>
#include <vector>
#include <pthread.h>
#include <functional>
#include "Log.hpp"
#include "Thread.hpp"
#include "LockGuard.hpp"
using namespace std;
static const int defaultnum = 5;

namespace ThreadNS
{
    class ThreadData
    {
    public:
        ThreadData(const string &name) : threadname(name)
        {
        }
        ~ThreadData()
        {
        }
        string threadname;
    };

    template <class T>
    class ThreadPool
    {
    public:
        static ThreadPool<T> *GetInstance()
        {
            if (instance == nullptr) // 这个instance是做什么的的？
            {
                LockGuard lockguard(&sig_lock); // 初始化锁，只需要一个？
                if (instance == nullptr)
                {
                    lg.LogMessage(Info, "创建单例成功...\n");
                    instance = new ThreadPool<T>();
                }
            }
            return instance;
        }
        bool Start()
        {
            for (auto &thread : _threads)
            {
                thread.Start();
                lg.LogMessage(Info, "%s is running...\n", thread.ThreadName().c_str());
            }
            return true;
        }
        void ThreadWait(const ThreadData &td) // 每个线程都需要调用，循环调用吧应该是
        {
            lg.LogMessage(Debug, "no task ,%s is sleeping...\n", td.threadname.c_str());
            pthread_cond_wait(&_cond, &_mutex); // 这个函数
        }
        void checkSelf()
        {
        }
        void ThreadRun(ThreadData &td)
        {
            while (true)
            {
                // 在运行之前，可以先查看是否符合要求
                T t;
                {
                    LockGuard lockguard(&_mutex);
                    while (_q.empty())
                    {
                        ThreadWait(td);
                        lg.LogMessage(Debug, "thread %s is waker\n", td.threadname.c_str());
                    }
                    t = _q.front(); // 我们刚刚的问题是没有给他赋值直接运行。
                    _q.pop();
                }
                t();
            }
        }
        void ThreadWakeup()
        {
            pthread_cond_signal(&_cond);
        }
        void Push(T &in)
        {
            LockGuard lockguard(&_mutex);
            _q.push(in);//入队列
            ThreadWakeup();
        }
        ~ThreadPool()
        {
            pthread_mutex_destroy(&_mutex);
            pthread_cond_destroy(&_cond);
        }

        void Wait()
        {
            for (auto &thread : _threads)
            {
                thread.Join();
            }
        }

    private:
        // 单例模式
        ThreadPool(int thread_num = defaultnum) : _thread_num(thread_num)
        {
            pthread_mutex_init(&_mutex, nullptr); // 锁，初始化，然后直接传过去用
            pthread_cond_init(&_cond, nullptr);
            for (int i = 0; i < _thread_num; i++)
            {
                string threadname = "thread-";
                threadname += to_string(i + 1);
                ThreadData td(threadname); // 初始化名字

                // 两种方法推送
                //  ThreadData td(threadname);
                //  Thread<ThreadData> t(threadname,bind(&ThreadPool<T>::ThreadRun,this,placeholders::1),td);
                //  _threads.push_back(td);//入队列
                // 第二种方法
                _threads.emplace_back(threadname, bind(&ThreadPool::ThreadRun, this, placeholders::_1), td); // placeholders这是占位符
                lg.LogMessage(Info, "%s is create ...\n", threadname.c_str());
            }
        }
        ThreadPool(const ThreadPool<T> &tp) = delete;
        const ThreadPool<T> operator=(const ThreadPool<T> &tp) = delete;
        queue<T> _q;                         // 运行队列
        vector<Thread<ThreadData>> _threads; // 疑问
        int _thread_num;
        pthread_mutex_t _mutex;
        pthread_cond_t _cond;

        static ThreadPool<T> *instance;
        static pthread_mutex_t sig_lock;
    };

    template <class T>
    ThreadPool<T> *ThreadPool<T>::instance = nullptr; // 只创建一个对象
    template <class T>
    pthread_mutex_t ThreadPool<T>::sig_lock = PTHREAD_MUTEX_INITIALIZER;

}